package com.suny.sf_server.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.suny.Pen.vo.PenSelectVO;
import com.suny.result.ResponseCode;
import com.suny.sf_server.redis.IRedisService;
import com.suny.sf_server.util.BloomFilterHelper;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import com.suny.Farm.domain.Farm;
import com.suny.Pen.domain.Pen;
import com.suny.sf_server.service.PenService;
import com.suny.sf_server.mapper.PenMapper;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.suny.sf_server.service.FarmService;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.transaction.annotation.Transactional;
import com.suny.Pen.dto.PenAddDTO;
import com.suny.Pen.dto.PenUpdateDTO;
import com.suny.Pen.vo.PenVO;
import com.suny.exception.BusinessException;
import com.suny.result.PageDTO;
import com.suny.utils.BeanConverter;
import com.suny.constant.RedisKeyConstant;
import com.suny.Pen.dto.PenQueryDTO;

/**
* @author sun
* @description 针对表【pen(圈舍管理表)】的数据库操作Service实现
* @createDate 2024-12-27 10:45:10
*/
@Service
@Slf4j
public class PenServiceImpl extends ServiceImpl<PenMapper, Pen> implements PenService {
    
    @Resource
    private FarmService farmService;
    
    @Resource
    private IRedisService redisService;
//    @Resource
//    private BloomFilterHelper bloomFilterHelper;
//    private static final String PEN_BLOOM_FILTER = "pen_filter";
//    @PostConstruct
//    public void initBloomFilter() {
//        log.info("开始初始化圈舍布隆过滤器...");
//        // 初始化布隆过滤器,预期数据量10000,误判率0.01
//        bloomFilterHelper.initFilter(PEN_BLOOM_FILTER, 10000, 0.01);
//
//        // 加载现有数据
//        List<Pen> pens = this.list();
//        List<String> penNames = pens.stream()
//                .map(Pen::getPenName)
//                .collect(Collectors.toList());
//        bloomFilterHelper.addAll(PEN_BLOOM_FILTER, penNames);
//        log.info("圈舍布隆过滤器初始化完成,共加载{}条数据", pens.size());
//    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(PenAddDTO dto) {
        // 验证牧场是否存在且启用
        Farm farm = farmService.getById(dto.getFarmId());
        if (farm == null || farm.getStatus() != 1) {
            throw new BusinessException("牧场不存在或未启用");
        }
        
        // 验证圈舍名称在同一牧场下是否重复
        checkPenNameExists(dto.getFarmId(), dto.getPenName(), null);
        
        // 保存圈舍信息
        Pen pen = new Pen();
        pen.setFarmId(dto.getFarmId());
        pen.setPenName(dto.getPenName());
        pen.setAmountLivestock(0);
        pen.setStatus(1);
        pen.setCreateTime(new Date());
        pen.setUpdateTime(new Date());
        
        save(pen);
//        // 添加到布隆过滤器
//        bloomFilterHelper.add(PEN_BLOOM_FILTER, pen.getPenName());
        clearCache(dto.getFarmId());
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(PenUpdateDTO dto) {
        if (dto == null || dto.getPenId() == null) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        // 验证圈舍是否存在
        Pen pen = getById(dto.getPenId());
        if (pen == null) {
            throw new BusinessException("圈舍不存在");
        }
        
        // 验证圈舍名称在同一牧场下是否重复
        checkPenNameExists(pen.getFarmId(), dto.getPenName(), dto.getPenId());
        
        // 更新圈舍信息
        pen.setPenName(dto.getPenName());
        pen.setUpdateTime(new Date());
        
        updateById(pen);
        
        clearCache(pen.getFarmId());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Integer penId, Integer status) {
        if (penId == null || status == null) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        if (status != 1 && status != 0) {
            throw new BusinessException("状态值无效");
        }
        Pen pen = getById(penId);
        if (pen == null) {
            throw new BusinessException("圈舍不存在");
        }
        if (Objects.equals(pen.getStatus(), status)) {
            throw new BusinessException("状态值未改变");
        }
        // 如果要停用，检查是否有未出栏牲畜
        if (status == 0 && pen.getAmountLivestock() > 0) {
            throw new BusinessException("圈舍内还有未出栏牲畜，不能停用");
        }
        
        pen.setStatus(status);
        pen.setUpdateTime(new Date());
        updateById(pen);
        
        clearCache(pen.getFarmId());
    }
    
    @Override
    public Page<PenVO> getList(PageDTO pageDTO) {
        // 1. 参数校验
        if (pageDTO == null || pageDTO.getPageNumber() <= 0 || pageDTO.getPageSize() <= 0) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        
        // 2. 生成包含分页参数的缓存key
        String cacheKey = String.format("%s:%d:%d", 
            RedisKeyConstant.PEN_LIST,
            pageDTO.getPageNumber(),
            pageDTO.getPageSize());
        
        // 3. 尝试从缓存获取
        if (redisService.isExists(cacheKey)) {
            return redisService.getValue(cacheKey);
        }
        
        // 4. 查询数据库
        Page<Pen> page = new Page<>(pageDTO.getPageNumber(), pageDTO.getPageSize());
        IPage<PenVO> voPage = baseMapper.selectPenVOPage(page);
        
        // 5. 处理空结果缓存
        if (voPage != null && voPage.getTotal() > 0) {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.CACHE_TIME);
        } else {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.EMPTY_CACHE_TIME);
        }
        
        return (Page<PenVO>) voPage;
    }
    
    @Override
    public Page<PenVO> getListByCondition(PenQueryDTO query) {
        // 1. 参数校验
        if (query == null || query.getPageNumber() == null || query.getPageSize() <=0) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
       // 2. 使用布隆过滤器预判断
//        if (query.getPenName() != null && !query.getPenName().isEmpty()) {
//            if (!bloomFilterHelper.mightContain(PEN_BLOOM_FILTER, query.getPenName())) {
//                log.info("布隆过滤器判断圈舍名称[{}]不存在,直接返回空结果", query.getPenName());
//                Page<PenVO> emptyPage = new Page<>(query.getPageDTO().getPageNumber(), query.getPageDTO().getPageSize());
//                emptyPage.setTotal(0);
//                return emptyPage;
//            }
//        }
        // 2. 生成包含查询条件的缓存key
        String cacheKey = String.format("%s:%s:%d:%d", 
            RedisKeyConstant.PEN_LIST,
            query.hashCode(),
            query.getPageNumber(),
            query.getPageSize());
        
        // 3. 尝试从缓存获取
        if (redisService.isExists(cacheKey)) {
            return redisService.getValue(cacheKey);
        }
        
        // 4. 查询数据库
        Page<Pen> page = new Page<>(query.getPageNumber(), query.getPageSize());
        IPage<PenVO> voPage = baseMapper.selectPenVOPageByCondition(page, query);
        
        // 5. 处理空结果缓存
        if (voPage != null && voPage.getTotal() > 0) {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.CACHE_TIME);
        } else {
            redisService.setValue(cacheKey, voPage, RedisKeyConstant.EMPTY_CACHE_TIME);
        }
        
        return (Page<PenVO>) voPage;
    }

    @Override
    public List<PenSelectVO> getSelectByFarmId(Integer farmId) {
        if (farmId == null){
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        String key=RedisKeyConstant.PEN_FARM_PREFIX_SELECT + farmId;
        if ( redisService.isExists(key)){
            return redisService.getValue(key);
        }
        LambdaQueryWrapper<Pen> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Pen::getFarmId, farmId)
                .eq(Pen::getStatus, 1);
        List<Pen> pens = list(wrapper);
        if (pens == null){
            throw new BusinessException("该牧场下没有圈舍");
        }
        List<PenSelectVO> list = BeanConverter.convertList(pens, PenSelectVO.class);
        redisService.setValue(key, list, RedisKeyConstant.CACHE_TIME);
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateInfo(Integer penId, String penName) {
        if (penId == null || penName == null || penName.trim().isEmpty()) {
            throw new BusinessException(ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }
        Pen penOld = getById(penId);
        if (penOld == null){
            throw new BusinessException("圈舍不存在");
        }
        LambdaQueryWrapper<Pen> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Pen::getPenId, penId);
        Pen pen = new Pen();
        pen.setPenName(penName);
        pen.setUpdateTime(new Date());
        update(pen, wrapper);
        clearCache(penOld.getPenId());
    }

    @Override
    public List<PenVO> getEnablePensByFarmId(Integer farmId) {
        String cacheKey = RedisKeyConstant.PEN_FARM_PREFIX + farmId;
        if (redisService.isExists(cacheKey)) {
            return redisService.getValue(cacheKey);
        }
        
        LambdaQueryWrapper<Pen> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Pen::getFarmId, farmId)
                .eq(Pen::getStatus, 1)
                .orderByDesc(Pen::getCreateTime);
        
        List<Pen> pens = list(wrapper);
        List<PenVO> list = BeanConverter.convertList(pens, PenVO.class);
        
        redisService.setValue(cacheKey, list, RedisKeyConstant.CACHE_TIME);
        return list;
    }
    
    private void checkPenNameExists(Integer farmId, String penName, Integer excludePenId) {
        LambdaQueryWrapper<Pen> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Pen::getFarmId, farmId)
                .eq(Pen::getPenName, penName);
        
        if (excludePenId != null) {
            wrapper.ne(Pen::getPenId, excludePenId);
        }
        
        if (count(wrapper) > 0) {
            throw new BusinessException("该牧场下已存在同名圈舍");
        }
    }
    
    /**
     * 清除圈舍相关缓存
     */
    private void clearCache(Integer farmId) {
        // 使用模式匹配删除所有圈舍列表缓存
        redisService.removePattern(RedisKeyConstant.PEN_LIST + ":*");
        redisService.remove(RedisKeyConstant.PEN_FARM_PREFIX + farmId);
        redisService.remove(RedisKeyConstant.PEN_FARM_PREFIX_SELECT + farmId);
    }
}




